# 作业：
# 1、通过python连接pymysql数据库，封装类方法
# 1.1、随机插入100条数据到数据库表，包括姓名、年龄、家庭住址、身份证号码
# 1.2、查询全部的数据
# 1.3、删除指定一条数据
# 1.4、封装批量删除方法，可以删除多条
# 1.5、可以指定增加单独一条数据到表里
# 以上每个操作步骤要写日志信息到log.txt里
import pymysql,random    #导入 pymysql,random（模板）
from faker import Faker  #从faker库中导入Faker类（板模）
from datetime import datetime #从datetime模块导入datetimelei（板模）
USER='root'               # 数据库用户名
PASSWORD='123456'         # 数据库密码
HOST='8.136.106.114'      # 数据库主机地址
DATABASE='zuoye'          # 数据库名称
faker = Faker(locale = 'zh_cn') # locale 设置国家为中国 zh_cn # 创建Faker实例，设置中文数据
class Student:           # 定义Student类
    def connect(self):   # 定义连接数据库的方法（模板），在定义完类之后，第一步必须进行此操作！！！！！
        self.db = pymysql.connect(user= USER,password=PASSWORD,host=HOST,database=DATABASE,cursorclass =
        pymysql.cursors.DictCursor)     #设置返回字典格式的游标（模板）
        self.cursor = self.db.cursor()  # 创建游标对（模板）
        str1 = f"当前时间为：{datetime.now()},连接数据库！" # 创建日志信息
        with open("log.txt",'a',encoding='utf-8') as f: # 打开日志文件（模板）
            f.write(str1 + "\n")                        # 写入连接日志（模板）
    def close(self):                                    # 定义关闭数据库连接的方法
        self.cursor.close()                             # 关闭游标（模板）
        self.db.close()                                 # 关闭数据库连接（模板）
        str1 = f"当前时间为：{datetime.now()},关闭数据库！"  # 创建日志关闭信息
        with open("log.txt", 'a', encoding='utf-8') as f: # 打开日志文件（模板）
            f.write(str1 + "\n")                         # 写入关闭日志
    def insert_100_row(self):                            # 定义插入100条记录的方法
        content_list = []                                # 创建空列表用于存储日志内容
        self.connect()                                   # 连接数据库（模板）
        for i in range(100):                             # 定义一个变量i循环100次
            name = faker.name()                          # 生成随机姓名
            age = random.randint(19,60)                  # 生成19-60的随机年龄
            address = faker.address()                    # 生成随机地址
            ssn = faker.ssn(min_age=19,max_age=60)       # 生成符合年龄范围的身份证号
            str1 = f"insert into student2(name,age,address,ssn) values('{name}','{age}','{address}','{ssn}')"    # 在python中，编写mysql语言
            self.cursor.execute(str1)                    # 执行mysql语句
            self.db.commit()                             # 提交事务
            str2 =  f"当前时间为：{datetime.now()}"+f"insert into student2(name,age,address,ssn) values('{name}','{age}','{address}','{ssn}')" + "\n"  # 构建成功日志信息 "\n"为换行
            print(f"{str1}插入成功！")                     #打印插入成功的信息
            content_list.append(str2)                    #将编辑的str2的内容插入在第32行创建的列表中，append代表插入至最后
        with open("log.txt",'a',encoding='utf-8') as f:  #写入于42行str2编辑的内容的日志信息至log。txt文件中
            f.writelines(content_list)                   #此内容是在写完第45行内容后，继续书写的固定模板
        self.close()                                     #此内容为，定义完第17行 定义完Student类，完成添加100条随机内容后，已经完成该操作，最后一步必须为关闭连接（模板）！！！！！

    def searchAll(self):                                 # 定义查询所有记录的方法
        self.connect()                                   # 定义连接数据库的方法（模板），在定义完类之后，第一步必须进行此操作！！！！！
        self.cursor.execute("select * from student2")    # 在python中，编写mysql语言，并执行mysql语句 此内容与第39，40行方法一致。上文中由于要编写的mysql语言内容太多，所以用一个变量str1来代替
        result = self.cursor.fetchall()                  # 用一个result来，获取所有结果。fetchall=查所有  fetchone=查一个
        for index,value in enumerate(result):            # 遍历在第52行编写的result的内容结果index（是下标）,value（是内容）
            print(f"第{index+1}条的数据为：{value}")        # 打印结果   index+1是因为index是从0开始的
        else:                                            # 打印结果
            print("输出完毕!")                             # 打印结果
        with open("log.txt",'a',encoding='utf-8') as f:  # 打开日志文件（模板）
            f.write(f"当前时间：{datetime.now()}，执行了查询操作！")   # 写入连接日志（模板）
        self.close()                                     #此内容为，定义完第49行 定义完searchALL类，查询所有记录后，已经完成该操作，最后一步必须为关闭连接（模板）！！！！！
    def delete_row(self,name):                           # 定义按姓名删除记录的方法
        self.connect()                                   # 定义连接数据库的方法（模板），在定义完类之后，第一步必须进行此操作！！！！！
        str1 = f"delete from student2 where name='{name}'"  # 在python中，编写mysql语言
        self.cursor.execute(str1)                        # 执行mysql语句
        self.db.commit()                                 # 提交事务
        with open('log.txt','a',encoding='utf-8') as f:  # 打开日志文件（模板）
            f.write(f"当前时间：{datetime.now()}，删除：{str1}  成功！" + "\n")  # 写入连接日志（模板）
        self.close()                                     #此内容为，定义完第49行 定义完delete_row类按姓名删除记录的方法后，查询所有记录后，已经完成该操作，最后一步必须为关闭连接（模板）！！！！！
    def delete_row_(self,*names):                        # 定义批量删除记录的方法  *names是可变参数，代表可以导入任意信息
        content_list = []                                # 创建空列表用于存储日志内容
        self.connect()                                   # 定义连接数据库的方法（模板），在定义完类之后，第一步必须进行此操作！！！！！
        for name in names:                               #  在单一名字name中遍历所有的names
            str1 = f"delete from student2 where name='{name}'" # 在python中，编写mysql语言，并执行mysql语句 此内容与第39，40行方法一致。上文中由于要编写的mysql语言内容太多，所以用一个变量str1来代替
            self.cursor.execute(str1)                  # 执行mysql语句
            self.db.commit()                           # 提交事务(模板）
            print(f"删除：{name}数据成功！")              # 打印成功信息
            str2 = f"当前时间：{datetime.now()}"+f"delete from student2 where name={name}" +"删除成功！" +"\n"
            content_list.append(str2)                  # 添加到日志列表
        else:
            print("全部删除完毕！")                       # 循环结束后打印提示
        with open('log.txt','a',encoding='utf-8') as f:
            f.writelines(content_list)                 # 批量写入日志
        self.close()                                   # 定义为关闭数据库连接

    def insert_one_row(self,name,age,address,ssn):     # 定义插入单条记录的方法
        self.connect()                                 # 连接数据库（模板）
        str1 = f"insert into student2(name,age,address,ssn) values('{name}','{age}','{address}','{ssn}')"
        self.cursor.execute(str1)                     # 在python中，编写mysql语言，并执行mysql语句 此内容与第39，40行方法一致。上文中由于要编写的mysql语言内容太多，所以用一个变量str1来代替
        self.db.commit()                              # 提交事务（模板）
        print(f"{str1}新增数据成功！")                  # 打印成功信息
        str2 =f"当前时间：{datetime.now()}" +f"insert into student2(name,age,address,ssn) values('{name}','{age}','{address}','{ssn}')" +"  新增成功！\n"# 写入日志
        with open('log.txt','a',encoding='utf-8') as f:# 写入日志
            f.write(str2)                              # 写入日志 str2为上面的内容
        self.close()                                   #此内容为，定义完第84行定义插入单条记录的方法定义完类，查询所有记录后，已经完成该操作，最后一步必须为关闭连接（模板）！！！！！
if __name__ == '__main__':                             # 主程序入口
    s1 = Student()                                     # 创建Student实例
    # s1.insert_100_row()                              # 可调用插入100条记录(注释状态)
    # s1.searchAll()                                   # 可调用查询所有记录(注释状态)
    # s1.delete_row("张磊")                             # 可调用删除单条记录(注释状态)
    # s1.delete_row_("马承泽","陈伟")                    ## 可调用批量删除记录(注释状态)
    s1.insert_one_row("吴京",55,"北京","11029788777892") # 插入单条记录

#
# 2、做一个学生点名系统，系统里支持：存入学生、更改学生、删除学生、点到学生姓名方法
#
# 存入学生（姓名、年龄、家庭地址、手机号）： 存入成功后，提示xxx存入成功
# 更改学生（姓名、年龄、家庭地址、手机号）：可以修改学生内容的任意一个字段
# 删除学生：删除的学生将不在展示
# 展示全部学生：可以看到全部的学生姓名
# 学生姓名：随机抽取任意一个存在的学生信息，然后打印：到！。举例： 刘闯到！
#
# 以上内容，需要连接数据库，每次的数据都需要增、删、改、查去做
import pymysql,random #导入 pymysql random（模板）
import traceback #导入 遇到错误后会返还
class System:    #定义一个system类
    def __init__(self,user,password,host,database): #类的初始化方法，用于接受数据库
        self.user = user                            # 将用户名保存为实例变量
        self.password = password                    # 将密码保存为实例变量
        self.host = host                            # 将主机地址保存为实例变量
        self.database = database                    # 将数据库名保存为实例变量
    def connect(self):                              # 定义数据库连接方法
        self.db = pymysql.connect(user = self.user,password= self.password,host=self.host,database=self.database,cursorclass =
        pymysql.cursors.DictCursor)                 # 创建数据库连接
        self.cursor = self.db.cursor()              # 创建数据库游标对象
    def close(self):                                # 定义关闭数据库连接的方法
        self.cursor.close()                         # 关闭游标
        self.db.close()                             # 关闭数据库连接
    def search(self,type:int,sql):                  # 定义查询方法，type参数决定返回单条还是多条结果  sql 是为了将 SQL查询语句 作为参数传递给 search 方法
        self.connect()                              # 建立数据库连接
        result = None                               # 初始化result  为什么不用[]?
        if type == 1:                               # 如果type为1，查询单条记录
            try:
                self.cursor.execute(sql)            # 执行SQL查询语句
                result = self.cursor.fetchone()     # 获取单条查询结果，用result接收
                self.close()                        # 关闭数据库连接
                return result                       # 返回查询结果
            except:
                self.db.rollback()#                  #回滚事务
                traceback.print_exc()               # 打印错误堆栈信息
                return result                       # 返回None
        elif type == 2:                            # 如果type为2，查询多条记录
            try:
                self.cursor.execute(sql)           # 执行SQL查询语句
                result = self.cursor.fetchall()    # 获取多条查询结果,用result接收
                self.close()                       # 关闭数据库连接
                return result                       # 返回查询结果
            except:                                  # 如果发生异常
                self.db.rollback()                 # 回滚事务
                traceback.print_exc()               # 打印错误堆栈信息
                return result                      #返回result none
    def __edit(self,sql):                          #  __edit 是其他方法（insert/delete/update）的内部工具方法   用于执行修改操作(插入/删除/更新)
        self.connect()                             # 建立数据库连接
        try:
            self.cursor.execute(sql)              # 执行SQL语句
            self.db.commit()                      # 提交事务
            self.close()                         # 关闭数据库连接
        except:                                    # 如果发生异常
            self.db.rollback()                   # 回滚事务
            traceback.print_exc()               # 打印错误堆栈信息
    def insert(self,sql):                     # 插入数据方法
        self.__edit(sql)                     # 调用私有__edit方法执行插入操作
    def delete(self,sql):                  # 删除数据方法
        self.__edit(sql)                   # 调用私有__edit方法执行删除操作
    def update(self,sql):                 # 更新数据方法
        self.__edit(sql)                 # 调用私有__edit方法执行更新操作

if __name__ == '__main__':              # 主程序入口
    d1 = System(user='root', password='123456', host='8.136.106.114', database='zuoye3')  # 创建System实例，传入数据库连接参数
    d1.insert("insert into student (name, age, address,phone) values ('张三', '22', '南方','11111111111')")      #插入三条学生信息
    d1.insert("insert into student (name, age, address,phone) values ('张四', '23', '北方','111111111111')")
    d1.insert("insert into student (name, age, address,phone) values ('张五', '24', '中方','1111111111111')")
#     d1.update("update student set name='张五' where name='张六'")
#     print(d1.search(2,"select * from student"))
# 删除学生：删除的学生将不在展示
# d1.delete("delete from student where name='张五'")
# print(d1.search(2,"select * from student"))

# 展示全部学生：可以看到全部的学生姓名
#     print(d1.search(2,"select * from student"))

# 3、类作业，统计镰刀和斧头的数量，要使用类方法
class ToolCount:
    liandao=[]
    futou=[]
    def __init__(self,toolsType):
        if toolsType == '镰刀':
            self.liandao.append("镰刀")
        elif toolsType == '斧头':
            self.futou.append("斧头")
    @classmethod
    def count_print(self):
        print(f"镰刀的数量为：{len(self.liandao)}")
        print(f"斧头的数量为：{len(self.futou)}")



# 4、新建学生成绩管理系统，随机生成100个 学生信息插入到数据库：
# 学生信息组成：学号、学生姓名、英语成绩、数学成绩、语文成绩、班级号（班级号有：1809A，1809B，1810A，1810B）
# 成绩划分为：优秀，良好，中等，及格，不及格。良好比中等好。
#
# 优秀：90—100之间（包括90）
# 良好：80-90
# 中等：70-80
# 及格：60-70
# 不合格：分数低于60分。
#
# 成绩管理系统提供以下方法：
# 《1》 查询所有英语成绩为优秀的、良好的、中等、及格和不合格的学生姓名和班级号
# 《2》 查询1809A，1809B，1810A，1810B每个班级的数学成绩，并且是降序返回
# 《3》 查询1809A，1809B，1810A，1810B每个班级的总人数，并且由大到小排序返回
# 《4》 查询英语、数学、语文成绩不合格的学生姓名和对应的班级号，按照不合格的人数，由大到小排序
#
# 5、定义一个图书管理系统类，图书可以新增、修改、删除，要求新增、修改、删除的图书，都要出现在数据库中
# 新增：图书名、作者名称、新建年月日
# 修改：图书名、作者名称、新建年月日
# 删除：图书删掉，且不在展示
# 查看：全量查询、精确查询、模糊查询需要用户传入形参来控制返回结果

